VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
  Persistable = 0  'NotPersistable
  DataBindingBehavior = 0  'vbNone
  DataSourceBehavior  = 0  'vbNone
  MTSTransactionMode  = 0  'NotAnMTSObject
END
Attribute VB_Name = "c32bppDIB"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit

' Credits/Acknowledgements - Thanx goes to:
'   Paul Caton for his class on calling non VB-Friendly DLLs that use _cdecl calling convention
'       Used when calling non VB-friendly zLIB dll versions
'   Alfred Koppold for his PNG, VB-only, decompression routines.
'       Used when zLib & GDI+ not available
'   Carles P.V for his pvResize logic
'       Used when manually scaling images with NearestNeighbor or BiLinear interpolation
'   www.zlib.net for their free zLIB.dll, the standard DLL for compressing/decompressing PNGs
'       Without it, we'd be limited to GDI+ for creating PNGs
'   coders like you that provide constructive criticism to make this class better & more all-inclusive
'       Without your comments, this project probably would have died several versions/updates ago
' For most current updates/enhancements visit the following:
'   Visit http://www.planetsourcecode.com/vb/scripts/ShowCode.asp?txtCodeId=67466&lngWId=1

' = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
'                                    O V E R V I E W
' = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
' About 32bpp pre-multiplied RGB (pARGB) bitmaps, if you are not aware.
'   - These are used specifically for the AlphaBlend API & are GDI+ compatible
'   Advantages:
'       - Images can be per-pixel alpha blended
'       - Opacity can be simultaneously adjusted during rendering
'       - AlphaBlend does both BitBlt & StretchBlt for pARGB images.
'       - Speed: AlphaBlend & GDI+ are pretty quick APIs vs manual blending
'   Disadvantages:
'       - The original RGB values are permanently destroyed during pre-multiplying
'           -- Premultiplied formula: preMultipliedRed=(OriginalRed * Alpha) \ 255
'           -- There is no way to convert pARGB back to non-premultiplied RGB values
'              The formula would be: reconstructedRed=(preMultipliedRed * 255) \ Alpha.
'               but because of integer division when pre-multiplying, the result is only
'               close and if this should be premultiplied again & converted again, the
'               alphas can get more transparent with every iteration.
'               Fully opaque pixels & fully transparent pixels are not affected.
'           ** Note: When images are converted to PNG formats, removal of
'              premultiplication is performed to meet PNG specs.
'       - Displaying a pre-multiplied bitmap without AlphaBlend will not result in
'           the image being displayed as expected.
'       - Not ideal for saving due to its size: SizeOf= W x H x 4
'           -- better to save source image instead or compress the DIB bytes using favorite compression utility
'           -- with GDI+ or zLib, image can be converted to PNG for storage
'       - AlphaBlend (msimg32.dll) is not included/compatible with Win95, NT4 and lower
'       - AlphaBlend on Win9x systems can be buggy, especially when rendering to DIBs vs DDBs
' Note that GDI+ is standard on WinXP+, and can be used on Win98,ME,2K, & on NT4 if SP6 is installed

' ----------------------------------------------
' About Win95, Win98, NT3.5, NT4 & WinME support
' ----------------------------------------------
' The routines will not honor AlphaBlend if it exists on those systems. Win98's version,
' for example, has several bugs that can crash the application when AlphaBlending to DIBs.
' NT4, NT3.5 & Win95 do not come with AlphaBlend and I do not have WinME to test with.
' Therefore, to support these systems, the Render routine will alphablend manually
' regardless if the AlhpaBlend API (msimg32.dll) exists on the system or not.

' Table of methods used for rendering dependent upon class settings and O/S
' ----------------------------------------------------------------------------------
' Win2K or Better?  GDI+ Available?  HighQualityInterpolation?  Method of Rendering
'       Yes              Yes                No / Yes            AlphaBlend / GDI+
'       No               Yes                No / Yes            GDI+ / GDI+
'       Yes              No                 No / Yes            AlphaBlend / Manually
'       No               No                 No / Yes            Manually / Manually
' Note that AlphaBlend does not support mirroring nor rotation nor high quality interpolation,
' so if these are applied when rendering, then class will use GDI+ if available,
' otherwise, manually rendered. By default, the class will initialize with
' HighQualityInterpolation=True if GDI+ is available.
' ----------------------------------------------------------------------------------

' Class Purpose:
' This class holds the 32bpp image. It also marshals any new image thru
' the battery of parsers to determine best method for converting the image
' to a 32bpp alpha-compatible image. It handles rendering, rotating, scaling,
' mirroring of DIBs using manual processes, AlphaBlend, and/or GDI+.
' What about DirectX?  Hmmmm...

' The parser order is very important for fastest/best results...
' cPNGparser :: will convert PNG, all bit depths; aborts quickly if not PNG
' cGIFparser :: will convert non-transparent/transparent GIFs; aborts quickly
' cICOpraser :: will convert XP-Alpha, paletted, true color, & Vista PNG icons
'               -- can also convert most non-animated cursors
' cBMPparser :: will convert bitmaps, wmf/emf & jpgs

' The parsers are efficient. Most image formats have a magic number that give
'   a hint to what type of image the file/stream is. However, checks need to
'   be employed because non-image files could feasibly have those same magic
'   numbers. If the image is determined not to be one the parser is designed
'   to handle, the parser rejects it and the next parser takes over.  The
'   icon parser is slightly different because PNG files can be included into
'   a Vista ico file. When this occurs, the icon parser will pass off the
'   PNG format to the PNG parser automatically.
' And last but not least, the parsers have no advanced knowledge of the image
' format; as far as they are concerned, anything passed is just a byte array

' = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
'                                       CHANGE HISTORY
' = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
' Accompanying FAQ.rtf is updated with every change
' 3 Mar 07
'   - Major bug realized.
'       Thru trial and error, I have found that calling iparseIsArrayEmpty can generate
'       "Expression Too Complex" errors in the routine that called that function. However, I
'       cannot determine why and when this happens. It is an inconsistent error. The same O/S
'       different PCs may or may not generate that error, but the iparseIsArrayEmpty is
'       definitely involved. Therefore, I have rewritten that function and modified every
'       line of code that calls that function.
' 2 Mar 07:
'   - Bugs recognized & fixed
'       - Using some zLib versions, PNG files may be much larger than expected. Fixed;
'           -- the variable passed to zLib was not being updated with compressed size; ByVal,ByRef issue
'           -- iparseValidateZLIB modified; could incorrectly identify calling convention for latest zLIB VB-version
'           -- special thanx to Robert Rayment for helping troubleshooting this -- sorry for crashing your pc ;)
'       - DIBs converted to palettized PNGs, without alpha, did not write the palette; fixed
'       - WinME only. Manually rendering to WinME produced artifacts from the alpha channel; fixed
'           -- modified Win9xBlend to use GetDIBits & SetDIBitsToDevice vs BitBlt; actually improved speed
'           -- special thanx to Herman CK for helping troubleshoot this; I don't have WinME
'       - This class' Initialize event corrected to positively identify Win2K and above.
'   - Added 5 more grayscale options: RedMask, GreenMask, BlueMask, RedGreenMask, BlueGreenMask
'       - Changed NTSC/PAL grayscale formula to be the default. See MakeGrayScale
'   - Modified GetDIBbits to allow retrieval of non-premultiplied pixels
'   - Modified SetDIBbits to accept either premultiplied or non-premultiplied pixels
' 27 Feb 07: by request
'   - Added 3 supporting functions to extract DIB bytes into a passed array
'       - GetDIBbits & SetDIBbits gets/sets DIB pixels
'           -- parameters to return bytes in various formats/structures combinations
'       - GetAlphaMask gets the DIB alpha values as an 8 byte/256 color, grayscale, array.
' 20 Feb 07:
'   - PNGparser conversion routines overhauled for speed, minor error found & fixed
'       -- PNGparser.InitializePalette did not correctly identify transparency index for Grayscale with simple transparency
'   - PNGwriter.FormatCaption & FormatText recognized non-spec text but did not prevent it from being written to PNG
'   - Modified PNGwriter to use zLIB compress2 function when available
'   - Error on my part, last post had debugging code using zLibVB.dll vs zLib.dll
'       -- no serious harm but versions prior to this update probably will not be able to use zlib.net's zLib.DLL
' 18 Feb 07:
'   - Bugs recognized & fixed
'       -- cPNGwriter.OptimizeTrueColor could error when converting to 24bpp images
'       -- cPNGwriter.OptimizeTrueColor was not writing the single transparency color for 24bpp converted images
'       -- cPNGwriter.Write_tRNS was not always writing the tranpsarency color either
'       -- PngPropertySet was not honoring the user-selected filterMethod property
' 16 Feb 07:
'   - More PNG support....(First non-GDI+ PNG writer in VB open source? Maybe.)
'       -- Added cPNGwriter class. Can create PNGs using zLIB.dll versions. See class for more
'       -- Added cCDECL class. Allows calling zLIB.dll when zLIB is not VB-friendly
'           -- added modParsers.iparseValidateZLIB to determine if zLIB is available & if VB-friendly
'           -- required adding some custom zLIB calls to end of cPngWriter & cPngParser classes
'       -- added PngPropertySet to allow PNG creation options not possible w/GDI+. Must have zLIB available
'       -- added PngPropertyGet to retrieve settings. Over a dozen options
'       -- added isZlibEnabled property to inform you if zLIB can be used or not
'       -- Modified SaveToStream_PNG & SaveToFile_PNG to use zLIB if GDI+ is not available,
'               but zLIB is or vice versa. zLIB is prefered when pngPropertySet is called
'       -- Zlib is 100% free and is available directly from source: www.zlib.net
' 11 Feb 07:
'   - Logic error. When a DIB is first initialized, the Alpha property is False.
'       This should have been Alpha=True. Note that if you are creating blank DIBs and rendering other
'       DIBs to the blank one, you should change the blank DIB's alpha and image format properties as
'       appropriate, dependent upon what you are rendering to that DIB. The Alpha property is used in
'       other routines and must be accurate, but the ImageType property is not used
'   - Added imgError to the ImageType property enumeration. This can assist when self-rendering
'       DIBs. If ImageType=imgError then Handle=0& and no DIB has been loaded into the class.
' 10 Feb 07:
'   - Added LoadPicture_FromOrignalFormat routine which will recreate the DIB from the bytes
'       cached during a call to LoadPicture_File or LoadPicture_Stream
'   - Added TrimImage routine which will remove excess transparency from an image
'       If a 256x256 image has 20x20 transparency border around it, the image will be reduced to 216x216
'   - When calling Resize, class would not save original image bytes if they existed; now it does
'   - Minor tweaks in rotation routines. Routines no longer overwrite class' Interpolation setting
'   - Logic error fixed: GDI+ when rendering mirrored & rotated used incorred DC X,Y coordinates
' 4 Feb 07:
'   - Added SaveToFile_PNG & SaveToStream_PNG as main class options, but only supported if isGDIplusEnabled = True
'   - Complete revamp of mirroring routines.
'       -- Added MirrorDIB routine that mirrors an image as needed & mirrored bytes are later rotated, scaled, rendered
'       -- Previous version attempted to calculate mirroring offsets when scaling, rotating, rendering -- failed
'       -- Following routines modified: pvResize, CopyImageTo, Resize, RotateAtTopLeft
'   - Logic error fixed: pvResize would clip wrong end of image when image is rendered past vertical bounds of DC.
'   - Modified startup to always set HighQualityInterpolation if GDI+ is available.
' 1 Feb 07: By request...
'   - Added mirroring support to following routines. Passing a negative destination width and/or height causes mirroring
'       - pvResize, Win9xBlend, CopyImageTo, Resize, RotateAtCenterPoint, RotateAtTopLeft & cGDIPlus.RenderGDIplus
'       - The msimg32.dll AlphaBlend API cannot perform mirroring. Therefore...
'       - Whenever mirroring is in effect and GDI+ can't be used, mirroring will be done manually
'       - GDI+, if available, will only perfrorm the mirroring if also rotating or if HighQualityInterpolation=True
'   - Found another minor bug. Broke GDI+ ability to Global blend while rotating. Fixed.
' 31 Jan 07:
'   - Fixed logic error when rotating negative angles via GDI+ (cGDIPlus.RenderGDIplus routine)
'   - Fixed logic error when manually resizing using BiLinear method (pvResize routine)
'       - routines were combining current pixel with one above, not below as required
'   - Fixed rotation routines (non-GDI+); now rotation while non-proportional scaling compatible
'   - Renamed cPNGParser.SaveTo routine to cGDIPlus.SaveToPNG. See Change 4Jan07 below for more
' 30 Jan 07:
'   - Added rotation options. See RotateAtCenterPoint & RotateAtTopLeft
'       - The two routines are identical except for how the destination X,Y coords are determined
'   - Added isGDIplusEnabled property to inform you whether or not GDI+ can be used on the system
'   - Added HighQualityInterpolation property to produce better renderings
'       - When set to True & GDI+ is available, any rendering is done by GDI+
'       - When set to True and GDI+ is not available, manual interpolation is done when scaling/rotating
'       - Property can be set to False manually to prevent GDI+ usage
'   - Added MakeGrayScale routine. Irreversible pixel modifications
'       - 3 different grayscale formulas are provided
'   - Relocated all GDI+ function calls and related code into a new class: cGDIPlus
'   - Relocated cPNGparser.ValidateDLL to modParsers as iparseValidateDLL
' 25 Jan 07:
'   - Modified Win9xBlend routine. Did not exactly replicate AlphaBlend when stretching; fixed I believe
'       -- Added extra checks in Win9xBlend & pvResize when alphablending on Win9x systems.
'       -- Prevents user from supplying invalid values that could cause routines to read past allocated memory
'       -- Properly handles negative destination DC offsets
'   - Changed iswin95Alpha property to isAlphaBlendFriendly to indicate whether or not AlphaBlend will be used
' 24 Jan 07:
'   - Now compatible with all O/S. Added Win95/NT4 support to the following routines:
'       CopyImageTo, Resize, Render
'       -- Added Win9xBlend & heavily modified then added Carles P.V.'s pvResize routine
'   - Bug found. cPNGparser.vbDecompress, under NT4, was causing crashes when trying to
'       resize a passed byte array. Fixed. Array is sized before it is passed to that routine
'   - Bug found. The iparseCreateShapedRegion routine was creating shaped regions bottom up
'       and this crashed on NT4. Fixed so regions are created top down always
'   - Bug found. In Win98 & possibly other O/S. When VB creates a 24bpp stdPicture as used
'       in cBMPparser, the stdPicture.Render method can write into the alpha channel of the
'       destination 32bpp DIB; 24bpp has no alpha channel. Routine tweaked to handle that.
' 17 Jan 07:
'   - Added CreateCheckerBoard method. This method will create a checkerboard pattern
'       as the DIB image. It will also set the ImageType property to imgCheckerBoard
'       so you know whether or not the image is class checkerboard or not.
'       This can be useful when the DIB should be displayed, but has no image to display.
'       The flag can be used to determine saving the image. If imgCheckerboard then noSave
'   - Added Resize method to permanently resize the image within the DIB
'   - Added optional resizing parameters to CopyImageTo routine
'   - Tweaked cBMPparser & cGIFparser to always modify alpha bytes regardless of transparency
'       -- Previously, when image had no transparency, the alpha bytes were not touched, rather
'          the class tracked this information via its Alpha property. But if you wanted to pass
'          the DIB to some other routine in your project and process/render it, the unmodified
'          alpha bytes could prove to fool those processes/routines
'   - Tweaked Render method to fully expose all of AlphaBlend's parameters
'   - LoadPicture_StdPicture could not process WMFs, fixed
'   - LoadDIBinDC fixed - could fail if multiple calls made passing a True parameter
'   - Error in LoadPictureEx prevented saving image bytes when PNG file was loaded, fixed
' 5 Jan 07:
'   - Added SaveFormat parameter to LoadPicture_File & LoadPicture_Stream
'       -- option has class cache the original bytes of the image if loaded
'       -- the 32bpp DIB will always be larger than the source bytes and for
'           usercontrols, saving the original bytes takes less space than
'           saving the DIB bytes.
'   - Added GetOrginalFormat to retrieve bytes when SaveFormat was passed as True
'   - Added SetOriginalFormat used when copying one DIB class to another
' 4 Jan 07:
'   - Added LoadPicture_ByHandle, LoadPicture_StdPicture, ScaleImage & CopyImageTo
'   - Added cGDIPlus.SaveToPNG (testing). Requires GDI+ or zLIB but will save 32bpp to PNG file or stream
'       -- not accessible, right now, from c32bppDIB. Must create cGDIPlus class to use it.
'   - Modified cICOparser's GetBestMatch algorithm
'   - Added imgPNGicon as an image type to distinguish PNG in Vista Icon vs standard .PNG file
'   - Bug found: removing overlays in cGIFparser.ConvertGIFto32bpp; forgot ByVal VarPtrArray(...)
'       which could cause crash when compiled. Fixed & double checked everywhere else too
' 1 Jan 07:
'   - Added SaveToFile & SaveToStream methods
'   - cBMPparser could possibly try to query unauthorized memory; fixed
'   - Methodology changed a bit when parsers return results. If image is definitely one
'       that the parser is responsible for & the image is invalid, the parser will return
'       True to prevent other parsers from handling the image. The c32bppDIB.Handle is used
'       to determine true success or failure.
'       -- cGIFparser when recognizing improperly formatted GIF would allow image to continue to
'           other parsers which then may cause those parsers to lock up.
' 26 Dec 06: First version
' = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =


' No APIs are declared public. This is to prevent possibly, differently
' declared APIs, or different versions of the same API, from conflciting
' with any APIs you declared in your project. Same rule for UDTs.
' Note: I did take liberties, changing parameter types, in several APIs throughout

' Used to determine operating system
Private Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" (lpVersionInformation As Any) As Long
Private Const VER_PLATFORM_WIN32_WINDOWS As Long = &H1&
Private Type OSVERSIONINFOEX
   dwOSVersionInfoSize As Long
   dwMajorVersion As Long
   dwMinorVersion As Long
   dwBuildNumber As Long
   dwPlatformId As Long
   szCSDVersion As String * 128 ' up to here is OSVERSIONINFO vs EX
   wServicePackMajor As Integer ' 8 bytes larger than OSVERSIONINFO
   wServicePackMinor As Integer
   wSuiteMask As Integer
   wProductType As Byte
   wReserved As Byte
End Type

' APIs used to manage the 32bpp DIB
Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
Private Declare Function CreateCompatibleDC Lib "gdi32.dll" (ByVal hdc As Long) As Long
Private Declare Function GetDC Lib "user32.dll" (ByVal hwnd As Long) As Long
Private Declare Function ReleaseDC Lib "user32.dll" (ByVal hwnd As Long, ByVal hdc As Long) As Long
Private Declare Function DeleteDC Lib "gdi32.dll" (ByVal hdc As Long) As Long
Private Declare Function SelectObject Lib "gdi32.dll" (ByVal hdc As Long, ByVal hObject As Long) As Long
Private Declare Function DeleteObject Lib "gdi32.dll" (ByVal hObject As Long) As Long
Private Declare Function CreateDIBSection Lib "gdi32.dll" (ByVal hdc As Long, ByRef pBitmapInfo As Any, ByVal un As Long, ByRef Pointer As Long, ByVal Handle As Long, ByVal dw As Long) As Long
Private Declare Function AlphaBlend Lib "msimg32.dll" (ByVal hdcDest As Long, ByVal nXOriginDest As Long, ByVal nYOriginDest As Long, ByVal nWidthDest As Long, ByVal nHeightDest As Long, ByVal hdcSrc As Long, ByVal nXOriginSrc As Long, ByVal nYOriginSrc As Long, ByVal nWidthSrc As Long, ByVal nHeightSrc As Long, ByVal lBlendFunction As Long) As Long
Private Declare Function SetStretchBltMode Lib "gdi32.dll" (ByVal hdc As Long, ByVal nStretchMode As Long) As Long
Private Declare Function GetObjectType Lib "gdi32.dll" (ByVal hgdiobj As Long) As Long
Private Declare Function GetCurrentObject Lib "gdi32.dll" (ByVal hdc As Long, ByVal uObjectType As Long) As Long
Private Declare Function GetIconInfo Lib "user32.dll" (ByVal hIcon As Long, ByRef piconinfo As ICONINFO) As Long
Private Declare Function SetDIBitsToDevice Lib "gdi32.dll" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal dX As Long, ByVal dY As Long, ByVal SrcX As Long, ByVal SrcY As Long, ByVal Scan As Long, ByVal NumScans As Long, ByRef Bits As Any, ByRef BitsInfo As BITMAPINFO, ByVal wUsage As Long) As Long
Private Declare Function GetDIBits Lib "gdi32.dll" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, ByRef lpBits As Any, ByRef lpBI As BITMAPINFO, ByVal wUsage As Long) As Long
Private Const STRETCH_HALFTONE As Long = &H4&
Private Const OBJ_BITMAP As Long = &H7&
Private Const OBJ_METAFILE As Long = &H9&
Private Const OBJ_ENHMETAFILE As Long = &HD&

' APIs used to create files
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As Any) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Const INVALID_HANDLE_VALUE = -1&
Private Const CREATE_ALWAYS = &H2&
Private Const GENERIC_READ = &H80000000
Private Const GENERIC_WRITE = &H40000000
Private Const FILE_ATTRIBUTE_NORMAL = &H80&

' used to create the checkerboard pattern on demand
Private Declare Function FillRect Lib "user32.dll" (ByVal hdc As Long, ByRef lpRect As RECT, ByVal hBrush As Long) As Long
Private Declare Function CreateSolidBrush Lib "gdi32.dll" (ByVal crColor As Long) As Long
Private Declare Function OffsetRect Lib "user32.dll" (ByRef lpRect As RECT, ByVal X As Long, ByVal Y As Long) As Long
Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type

' used when saving an image or part of the image
Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (Ptr() As Any) As Long
Private Type SafeArrayBound
    cElements As Long
    lLbound As Long
End Type
Private Type SafeArray
    cDims As Integer
    fFeatures As Integer
    cbElements As Long
    cLocks As Long
    pvData As Long
    rgSABound(0 To 1) As SafeArrayBound ' reusable UDT for 1 & 2 dim arrays
End Type

Private Type ICONINFO
    fIcon As Long
    xHotspot As Long
    yHotspot As Long
    hbmMask As Long
    hbmColor As Long
End Type
Private Type BITMAPINFOHEADER
    biSize As Long
    biWidth As Long
    biHeight As Long
    biPlanes As Integer
    biBitCount As Integer
    biCompression As Long
    biSizeImage As Long
    biXPelsPerMeter As Long
    biYPelsPerMeter As Long
    biClrUsed As Long
    biClrImportant As Long
End Type
Private Type BITMAPINFO
    bmiHeader As BITMAPINFOHEADER
    bmiPalette As Long
End Type

'// Added by Bryan Utley

Private Type RGBQUAD
    B           As Byte
    G           As Byte
    R           As Byte
    A           As Byte
End Type

Private Type SAFEARRAY2D
    cDims       As Integer
    fFeatures   As Integer
    cbElements  As Long
    cLocks      As Long
    pvData      As Long
    Bounds(1)   As SafeArrayBound
End Type

'// --------------------------


Private Const AC_SRC_OVER = &H0&
Private Const AC_SRC_ALPHA = &H1&

Public Enum eImageFormat    ' source image format
    imgError = -1  ' no DIB has been initialized
    imgNone = 0    ' no image loaded
    imgBitmap = 1  ' standard bitmap or jpg
    imgIcon = 3    ' standard icon
    imgWMF = 2     ' windows meta file
    imgEMF = 4     ' enhanced WMF
    imgCursor = 5  ' standard cursor
    imgBmpARGB = 6  ' 32bpp bitmap where RGB is not pre-multiplied
    imgBmpPARGB = 7 ' 32bpp bitmap where RGB is pre-multiplied
    imgIconARGB = 8 ' XP-type icon; 32bpp ARGB
    imgGIF = 9      ' gif; if class.Alpha=True, then transparent GIF
    imgPNG = 10     ' PNG image
    imgPNGicon = 11 ' PNG in icon file (Vista)
    imgCursorARGB = 12 ' alpha blended cursors? do they exist yet?
    imgCheckerBoard = 64 ' image is displaying own checkerboard pattern; no true image
End Enum

Public Enum ePngProperties ' following are recognized "Captions" within a PNG file
    txtTitle = 1           ' See cPNGwriter.SetPngProperty for more information
    txtAuthor = 2
    txtDescription = 4
    txtCopyright = 8
    txtCreationTime = 16
    txtSoftware = 32
    txtDisclaimer = 64
    txtWarning = 128
    txtSource = 256
    txtComment = 512
    ' special properties
    txtLargeBlockText = 1024 ' this is free-form text can be of any length & contain most any characters
    dateTimeModified = 2048  ' date/time of the last image modification (not the time of initial image creation)
    colorDefaultBkg = 4096   ' default background color to use if PNG viewer does not do transparency
    filterType = 8192        ' one of the eFilterMethods values
    ClearAllProperties = -1  ' resets all PNG properties
End Enum

Public Enum eTrimOptions    ' see TrimImage method
    trimAll = 0             ' can be combined using OR
    trimLeft = 1
    trimTop = 2
    trimRight = 4
    trimBottom = 8
End Enum

Public Enum eScaleOptions   ' See ScaleImage method
    scaleToSize = 0         ' [Default] will always scale
    scaleDownAsNeeded = 1   ' will only scale down if image won't fit
    ScaleStretch = 2        ' wll always stretch/distort
End Enum

Public Enum eGrayScaleFormulas
    gsclNTSCPAL = 0     ' R=R*.299, G=G*.587, B=B*.114 - Default
    gsclCCIR709 = 1     ' R=R*.213, G=G*.715, B=B*.072
    gsclSimpleAvg = 2   ' R,G, and B = (R+G+B)/3
    gsclRedMask = 3     ' uses only the Red sample value: RGB = Red / 3
    gsclGreenMask = 4   ' uses only the Green sample value: RGB = Green / 3
    gsclBlueMask = 5    ' uses only the Blue sample value: RGB = Blue / 3
    gsclRedGreenMask = 6 ' uses Red & Green sample value: RGB = (Red+Green) / 2
    gsclBlueGreenMask = 7 ' uses Blue & Green sample value: RGB = (Blue+Green) / 2
End Enum

Public Enum eFilterMethods
    filterDefault = 0     ' paletted PNGs will use filterNone while others will use filterPaeth
    filterNone = 1        ' no byte preparation used; else preps bytes using one of the following
    filterAdjLeft = 2     ' see cPNGwriter.EncodeFilter_Sub
    filterAdjTop = 3      ' see cPNGwriter.EncodeFilter_Up
    filterAdjAvg = 4      ' see cPNGwriter.EncodeFilter_Avg
    filterPaeth = 5       ' see cPNGwriter.EncodeFilter_Paeth
    filterAdaptive = 6    ' this is a best guess of the above 4 (can be different for each DIB scanline)
End Enum

Private m_PNGprops As cPNGwriter    ' used for more advanced PNG creation options
Private m_StretchQuality As Boolean ' if true will use BiLinear or better interpolation
Private m_Handle As Long        ' handle to 32bpp DIB
Private m_Pointer As Long       ' pointer to DIB bits
Private m_Height As Long        ' height of DIB
Private m_Width As Long         ' width of DIB
Private m_hDC As Long           ' DC if self-managing one
Private m_prevObj As Long       ' object deselected from DC when needed
Private m_osCAP As Long         ' 1=Can use AlphaBlend (Win2K+), 2=Can use GDI+ (Win98+), 4=Can use zLib. See Class_Initialize
Private m_Format As eImageFormat ' type of source image
Private m_ManageDC As Boolean   ' does class manage its own DC
Private m_AlphaImage As Boolean ' does the DIB contain alpha/transparency
Private m_ImageByteCache() As Byte  ' should you want the DIB class to cache original bytes
' ^^ N/A if image is loaded by handle, stdPicture, or resource

Public Function LoadPicture_File(ByVal FileName As String, _
                                Optional ByVal iconCx As Long, _
                                Optional ByVal iconCy As Long, _
                                Optional ByVal SaveFormat As Boolean) As Boolean

    ' PURPOSE: Convert passed image file into a 32bpp image
    
    ' Parameters.
    ' FileName :: full path of file. Validation occurs before we continue
    ' iconCx :: desired width of icon if file is an icon file. Default is 32x32
    ' iconCy :: desired height of icon if file is an icon file. Default is 32x32
    ' SaveFormat :: if true, then the image will be cached as a byte array only
    '   if the image was successfully loaded. Call GetOrginalFormat to retrieve them.
    
    ' Why would you want to save the bytes? If this is being used in a usercontrol,
    ' saving the bytes will almost always be less size than saving the 32bit DIB.
    ' Additionally, these classes have the ability to get different sizes from
    ' the original source (i.e., WMF, icon, cursors) if available, but if the
    ' 32bit DIB is saved, it is a constant size. The potential of different sizes
    ' could allow better resizing of the image vs stretching the DIB.

    On Error Resume Next
    If Not iparseFileExists(FileName) Then Exit Function
    If FileLen(FileName) < 57 Then Exit Function
    ' no image file/stream can be less than 57 bytes and still be an image
    If Err Then
        Err.Clear
        Exit Function
    End If
    Dim aDIB() As Byte  ' dummy array
    LoadPicture_File = LoadPictureEx(FileName, aDIB(), iconCx, iconCy, 0&, 0&, SaveFormat)
    
End Function

Public Function LoadPicture_Stream(inStream() As Byte, _
                                    Optional ByVal iconCx As Long, _
                                    Optional ByVal iconCy As Long, _
                                    Optional ByVal streamStart As Long = 0&, _
                                    Optional ByVal streamLength As Long = 0&, _
                                    Optional ByVal SaveFormat As Boolean) As Boolean
    
    ' PURPOSE: Convert passed array into a 32bpp image
    
    ' Parameters.
    ' inStream:: byte stream containing the image. Validation occurs below
    ' iconCx :: desired width of icon if file is an icon file. Default is 32x32
    ' iconCy :: desired height of icon if file is an icon file. Default is 32x32
    ' streamStart :: array position of 1st byte of the image file. Validated.
    ' streamLength :: total length of the image file. Validated.
    ' SaveFormat :: if true, then the image will be cached as a byte array only
    '   if the image was successfully loaded. Call GetOrginalFormat to retrieve them.
    
    ' Why would you want to save the bytes? If this is being used in a usercontrol,
    ' saving the bytes will almost always be less size than saving the 32bit DIB.
    ' Additionally, these classes have the ability to get different sizes from
    ' the original source (i.e., WMF, icon, cursors) if available, but if the
    ' 32bit DIB is saved, it is a constant size. The potential of different sizes
    ' could allow better resizing of the image vs stretching the DIB.
    
    If iparseIsArrayEmpty(VarPtrArray(inStream)) Then Exit Function
    If streamStart < LBound(inStream) Then streamStart = LBound(inStream)
    If streamLength = 0& Then streamLength = UBound(inStream) - streamStart + 1&
    If streamLength < 57 Then Exit Function
    ' no image file/stream can be less than 57 bytes and still be an image
    LoadPicture_Stream = LoadPictureEx(vbNullString, inStream, iconCx, iconCy, streamStart, streamLength, SaveFormat)

End Function

Public Function LoadPicture_Resource(ByVal ResIndex As Variant, ByVal resSection As Variant, _
                            Optional VbGlobal As IUnknown, _
                            Optional ByVal iconCx As Long, _
                            Optional ByVal iconCy As Long, _
                            Optional ByVal streamStart As Long = 0&, _
                            Optional ByVal streamLength As Long = 0&) As Boolean

    ' PURPOSE: Convert passed resource into a 32bpp image
    
    ' Parameters.
    ' ResIndex :: the resource file index (i.e., 101)
    ' ResSection :: one of the VB LoadResConstants or tion An01)gng, Bon  orY'class fh As Lhanage its owl ResInffect and GDhandrev, _
         lass fh A a lass fh Abyten:bType = fect VQ, 10n Exit GDhandrev,          = &H As f the Vs BitBly woulyVal Re 0&,being use          =ds(1)   As SafeArrayBound
End Typen loWay
  te
hed as a byte array on nd TClAGrian is an icon file. Default itch =uage fsto a 32bpp image
.bHue, thedrev,          = &H As fte array on n  = &l ByVal streaf-managing one
Private m_S  
    ' PURPOSE: Convert passed array into an image
'    C7       NERIC_W
    If FileLen(FilemIB's alleavcwg
    3rL<7    wleam)ndows mVrocwg
lue: Rss2.dll"            esults. If 'O f the Vs BitBly woulyVal  0         k       k       xByVau esuSE: Cooarray oTc
Prsion

Public Function LoadPicture_Stream(inStream(eImage method
    scaleToSizaving tinStream(eImndex A e = 0    ' nsourcn :: one ofam(eImndess size than saviyublic osave the bytes? If this than 57 thaomhaomhaomhao df thiblic osave thegth As Lo than saviyubli_g system
Pra

Pusf an ic-1&
Private Const Cm Declare +,Load&x.d then added CIdess sNded by PURPsan saviyublinaltandard cursor
    imgBmpARGB = 6 some hiblic oA +,Load&x.d theny the RetType property      C7geTo, Resize, Render
'       -- Added Win9xBlend & heavily modified then added g      lN=ng
    cLoetReoule

End Funodified then added g     o _
        s.
&ofceFilte[ldeoule
















e Const OBJ_ENHMETAFILE Aaession Ast generate that error, bn added s Long
End Type
Private Type Long
d is just a by0000
P






e Fun,- added P-enMask
'       - Chang R=R*.t Saf ParametSderen lo:ehao dfearAllProperties = -1  ' ureEY     he Vs BitBly wove  is an icon es
   e  is   is   iseam(et to retri5    is   iseam(et tOi is just a by0000
P
s just a by00000
P
s C'      
P
s just a by0l" Alias "RtlMoveMemors   iseam(et  savD p Aliasity to Global .  BitBly wove  is aaaaaaaaaaaaaaaalte[ldoFun,eaaaimgEMF = 4     ' enhanced WMF
  ccurs beforeh = odn: CooarradoFs5omhaomhanst OBJ_ENHMMF = 4      mhanst OB't fit
    ScaleSn OffsetRect Lieis   isea classes have the abili'e adve im as Byte
clafvObj sn loW<SbStar= 4  (eIaes? If this than 57 thaomhaomhaomhao df aessaaaa saaaa = 11 '  beforeh = odn:1 '  be"ing the DIB byt image vs stretcaIf thS[meter
'   - Er =ds(1)    stdPicture, or resSderen lo:ehao dfearAllProperties = -1  ' ure,
' r=EsrderefearAlVal iconCy At to retri5 rAlVal iconCys Long, ByV= 4  (es when trying to
'       resize a passed byte array. Fixed. Ahen ryV= 4  (es. Fixed.n loW<ght causes micon fgay. Fixed. Ahen r, when parsearAllProourceixeFixed. 
    3rL<7    wl Fixed.n loture 
P
s just a bt tue tional BhAFparser.ConvertGIFxeFixed. 
      wl Fixedfonve,t tumst a bnalFpl BEpl BEpl BEpl BEpl BEpl B)DnStreamWle, bP
snStsle, bPulyValoust a by0000
P






e Fun,- added P-enMask
'    true, thenT.he bytes will almost always be less size than saving the 32bit DIB.
    ' Additionally, these classes have the ability to get different sizes from
    ' the origiiiiBue, thenT.heal resSection s from
, iconCx, ik
'    tra'
, i = -1  ' no DIBrwizes or rrhp = -1  ' uro( Decl=&1rNObj As Long  DertGIFO 'O f the Vsd2bpp image
 Vsd2bze l wUsodiffered2bpp image
 Vsd2bze l wUso
2nnel; fi  destib path of file. Valie
 Vshese clib pa.x As cPNGwas jao dfearAllPiSjao dieT1your ib paarsByVainitialized, th     -- se clib paByVa he imag Addit





e ScaleSn OfVa hetainitializGrian is an ib lessn Of
 5 OfVa hetOe intIcon = 3    emIB' source (i.e., W     , W   Iconr/HMMF = W   oill. However, c a buro( Decl c a buro( Dng * 12   oill. However, Icon = rhp oweveruhers stretcLong, _
       rffecxeated.
2bpp image
.bHue, thedr, _
       hedr, _= odn:&l ByValker to always modifes m.Epl BEpl B)DnS-1  ' uro( Decl=&1rNObj As Long  DertGIFO 'O f the Vsd2bpp image
 Vsd2bze l wUsodiffered2bpp image
 Vsd2bze l wUso
2nnel; fi  destib path of file. Valie
 Vshese clib pa.x As cPNGwasas jae array. nCx, outwhen pre, theed resource into a 32bpp image
  d:hods vacPNGwas jao djao dieT1your2bze            Optional VbGlobaAiginal bytes
' ^^ee&ways modifeslend &nal bytes
' ^^ee&bGlobaAent si'caleStretch 2pe
d2bze l wUso
2nnel; fi  destib path of 'modicePackMajst /onal By DeclFpl BEpPmat :: if = -1valid, l
    Boetch 2peA ByValker tomage
 Vsd2bze l wUso
2nnel; fi  destib path of file. Valie
 Vshese clib pa.x As cPNGwas jao dfearAllPiSjao dieT1your ib paarsByVainitialized, th     -- se clib paByVa he imag Addit





e ScaleSn OfVa hetainit DeclFpl BEpPmath     -- s8it DeclFpl BE -- se not.
'       This can 
Pubd'      k    y0000
oxlFpl BE -Cal icsd2bzzzzzzzzz1oed Wiral icsd2bzzzzzze les is saved, isd2b, oud2bzzzzzzzzz1oed Wiral icsd2bzzzs saved, isddal icsd2bdis is aIB byt image vs stretcn samplzzzzzzbzzz is aIB by000
 stretcn samplzzzzzzbzzz is aIB by000
 stretcn saIi
End Type

Private Type SAFEARRAY2D
    cDimhe checkerboard pioType SckerbF
  cczzz1oed WiralpsCP(redone o2bdis is ae vs stoTyreWb       and this cesouttbze l wUso
2nnel;s Bo
    ' Pard pioTypei_
      ot < LBound(inStctucn(cti  Deresource inodiffer  true, thenT.URPOSE: CondicePackMajst /onal By DeclFpl BEpPmat :: if = -
    i:: .QT As Boolean
    
    ' d    e bytsfnctucn(cti  Deresounct;   rtg  imgCheclPmaG,p9



,zz1oed resource inTomhanst OBJ_ENHMMF = 4 Additiozs saved, Checllare Function Fillz1oRer.ConvertGIFxeFixed. 
 rFPngProperty d as a (nCy :: deste
    R       e0ze caGIFxeFixed.1oRer.ConvertGuxENHMMF = 4 Additioz, _
 4ertGIFonal - Er =caGIFzzz1oeds ae vs stoTyreWbIFzzz1Ayl"        
 4erPPPPPe0ze caGIFxeA4erPPPPPdded by Bryan Utleyee
  iplied pm(eImageWbIFzzz1AyoeFix)s1Ayl"      =As Lone&bGlo1Ayl"        If thph As Lhanage its owl Re d    ety tpr&outtbze l wUso
2nnel;s Bo
  usesxong, l; f = = te invD p Aliasity to Globaltl /sity to Globaltl /sity to invD p Aliasit. nCCm Declare +,Load&x.d thenE    -tGIFO 'O fem Declare +,Load ^^ N/A if image is loaded by handle, stdPicture, or reso  destib pattAuthor
  32bpp ARGB
 N/A if image is loaded by handle, stdPicturrunctre       
 4erPloaded by han[ldoFulGreenMf iIFxeA4erPes?l; f = = tLoadnalRg iplie+at erfearAllProperties = -1  Red+Green) / outwhen pre, theed resource into a 32bpp image
  d:hods vacPNGwas jao djao dieT1youfilterDefaus jao djao dieT1Xdle, stdPicture, or resobe accurate, ben ExitailterDezong
ds ae vs stoTd resourcetal ByVal iconCy As Long, _
                 arSae l icture, or noa5isddal icsd2bdExitoa5isa1Cy As Long, ritten Lods vacPNGwas ByVal stred rrrunctre    ing en Lav. samplzzzzzzilete array on nd   -- se clib paByVa he imag plzzzzzziletlasses havcu:&l samplzzzzzzi)=stib path of file. Valie
 Vshese clib pa.x As Vsd2bze l' uses only ceFilte[ldeoVt a bnalFpl BEpl BEpl BEpl BEpl Bplie+at erfeata best guess of the aboib paByGr re/dieTc used erfeat  is   iseLib "keclFpl BE -- se nnnnnnnnuxENHMMs Vsd2txEN t guess of thet guess of t    vcu:&l srace inodiffer  trueCof thet guess of t ng, l;oRer.Conver at sOB't faEby handle, stdPicture, or resource

Public Function LoadPicture_File(Bc erfeat sOBoture, or resoe vs le0ze caGIFxeA4ersddalBc rO=rray oucn(cti  DeresFilsa.x Aunction Lto a 32bpp image
  d:hods vacPNGwas jn
Private m_Handle As Long        ' handle to 32bpp DIB
Private m_Pointers own DC            esults  isea Long
Pr2bpp DIB
Pized, th     -- se clib paByVa he imag Addit





e ScaleSn OfVa' r=EsrderefDOe intong
Privat+andle As Long   erfeat   L*n icon file. Defaucjao    - Whenev stoTd resRheckerboard pion DC           file.eckerboEg, ByRef piconin DIBrwizes or rRheckerboakerboard  mostKconin D Long
 itsmage
  d:hods vacPNGwas jn
Private m_Handle As LoStsle,    txtWarni  destibata bestl; fi  d resRheckerboard p     Optional ByVal ithetestination X,Y coates a 24jao dfearAllPiSjao dieT1your ib paarsByVainitialized, th     -- se clib paByVa he imag Addit
mepi saved,aPBE -Cal iong
 patlib paB/S(nitiali=rray oucn(cti  DeresFilsa.x Aunction Lto a 32bpp iyValfpp Dre_FitxEN t guess of thet guess of t    if image isisfd pion DC  txEN pioTuRGB = (Red+G.mX(1X(1X(1f t       cDimhe t si'hlfpp vvvvvvvvvENHMMF = 4 Additherwith any APIibpe-tGIFO 'O fem te invDD  -- se clibT fte arrKds(1)   Aibpe- paarsods her/the DIB class to cache origtWarniaya  h 2peda  h nction Lto a 32bpp image
  IoTd resfte akerboard pion DC           fileIf iparseIsLto a 3      i her/thnStctucn(caleTofoard piondPicture, or resobe accu image is loaviyublic osave the bytes? If this than 57 thaomhaomhaomhao df thiblic osave thegth As Lo thaVal streamSaarshe (caleTo          H bnalFpl BEpl Ba checkerboard pattern
'       as the DIB image. It will also set the ImageType property to imgCheckerBoard
'       so you know whether or not the image is class checkerboard or not.
'       This can be useful when the DIB should be disO2.dll" (ByVal hdc Ase usefudded by Bryan Utlet  is   iseLib "keclFplm Ase Val hwnd As a   oCwultd, isd2b, oud2bzzzzzzzzz1oarnotNiotNiotNio:wraycaIB by stoTd resRheeeeeeewnd As         clFp[Nbzzzzzzzzz1oarnotNil hwbattern
'   an impe-tGIFO 'Oion Dp\e As String,rn class options, but onlboard t  is    of tmd    e bytsfnctucns   iseLib "keclFpl BE -- se nnnnnnnnuxENHMzz1oarnotNOBJ_ENHMM = FO 'O f the Vsd2bpp image
 Vsd2boar&/eutNOBJ_ENHMM con file (Vista)
    imgCursorARGB = Val hwnd As a  Dre_Fia)
    e (Vistaar&/eutNOBJ_o(ion orARGB =t
'    l/eutNOBile (Vista)
 e (c5his thnal ByVal iconver in DI orARGp, _
Trrrrrrnm,rn crsxo =t
'    l/eutNOBile (Vis1'  rroutineurce

Pge       .x AunVshese clib p
Pge e1Roe ori"pe (Vis1'  rroutineurce

Pge     =/eu   b "kernecke ori"pneurce
destibseu   b ug) As &u   b 2uthor
oSjao dieT1yourh ofVis1' lrnecke oribirnotbT fte arrKds(1)   AibpCayScawturh ofVong, lpBuffer As erfeat sOBotuBotuBotuBotuBoa= 4     ' enhanced WMF
  ccccccccccccasresRhenhanced WMFa&ge     =/eu   b "kernecke ori"pneurce
destibseu   b ug) Asi(e esmage .    ' e   ' e   ' e classeseckerBoardn crsxo ' e h uses Blue & Grimage scale d/t  ' e clas(e Nn ib lessn Of
 5on s  uses orOSE: ucns  lo1Ayl"        b ugTc used erfeat  is   iseLP vacPNGwas joust a by000000000000B)DnSt,stibata bB/ 3
 As Long
    reso  
rDeLP vacPNGwas jo: md:hodpe (Vi   resize a RsespiondeVshesleSn OfLftation routines.  clFp[NbzzzzzzzzsT fte arrKds(1) eVshesl -1valid, l
 -- se nnnnnnnnuxENHMMs Vsd2txEN tsRhenIPNGwas jo:3'ag plzzzzzs Vsd2txEN t'"oOmpe-tGIFO 'OioaU=nsparent GAtCentPNGBther
'iasaByVamodparentGIFAage
    tCen-
      t the        b ugTc
,&'o1ed rparent GAtCent   own DC   Q eVlz1oH  ' st' saving tare FunctiD,
'       ed rpaGIFAas LongplzzzzzzbA path of uObjecttine. Irasso Vista  xH(Vi   res -1vource imagtKds(1)   AibenE   aeD,
'lge     =/eu   b "kernecke ori"pneurce
destibsehorn;y0ze caGIFxeA4ersd0entGIFAage
    path of ubRARARrsxo ' e h uses  oOmpdByRef Sou       not t ubRARARrsxo ' e h uses  oOmpdB' st'eaSe
desngplzzzzzzbAaByGr rfbB/ 3
 As Lonp Dre_Femepi savedo=/eu   b "keu     b ugTc
,&'o1ed rparent GAtCent   own DC   Q eVlz1oH  ' st' saving tare FunctiD,
'       ed rpaGIFAas LongplzzzzzzbA path of uObjecttine. Irasso Vista  xH(Vi   res -1vource imag(hasson vs standary(.. c a000000000000BCsavingkB = (R+G+B)/3
    gSsta  xH(Vi   res -1vource imag(hasson vs standaryra1vource Wiral eee1vource imag(hasson vs(hassoPicture, oI(Gs -1vwas ve,t tumst amtral eeeeucn(cti  DeresFilsa.x Aun bit wpdByRef Sou  t DI Ymst amtral eeeeucn(cti  DeresFilsa.x 2ine.4dis isa.x scaleal hTemplateFilsavi:(aal eee1e classeEYnral eeeeucn(ctissn Of
 5on s  uses oi&urce (i.e., W    zi)=stib path oazbAaB  h uses  oOmpdB' st'e5foPictureed width of i useseal hTempls  urlt si'hlfpp seslz1oH  'i&urce (i.e., W    zi)=stib pale (Vista)
    imgCura bnalFpl BEpl Bwoitnd 1e clas ' e ctiolpha channel  degzong
ds aeis   i 1e clas ' e ctture, or noVal stred rrrul  degzong
ddddddddddddx 2inne Asaal eamrsBoaU=nspareoCent   own DEpl B)DnSm  ety ti.e., W    zi)=)ypDIFO 'OioaU=nspartGong
daBoaU :: total idestibseu   b ug) Asi(eibsleSn OfLft = = = =xeA4erPPPPPdd oOmp
  IoTd resfte akerboacPNGwas jn
Pri
    gSnd 1nSt,stiaars0mageWbIFzzz1AyoeFconinfo OfLft"yGr rfbB/ 3
 Apthiblicsaved,aPFconinfcimagtKds(1)   AibenE   aU eeeePSn Ofsa.x Aun biti&urce (i.e., gLrpaGIFAth (i.e., gLrpaGIFbB/ 3
 AsoCent V5on s  uses orOSE:fh As Lhal1youfilteDnSm  ety tiEt is a constant spadx retca Long) As  Ptr1dn crsxo ' e / 3
 Apthil iconCy As Long,dIfh As L ' e / 3glFp[NbotuBotuBotu= the .
 Apthil icone
    
   e&pe/ 3glFp[NPPe0ze caGIF
    ' b:hods vacseslend &sY ' d .e., WyGr rfb position of&'o1ed rpm     This can be tGInd &seeP'ib path oazbe., WyGr rfb position of&'o1ed rpm     This can be'iear
     IFAi&o is aaaaaGr rfb Ors0mmmmmmmmmmmmmmmmmmmmmmm,l,
   zed,
   -tGIFO mmmmmmmmmmmmmmmmmCs Aun bNasses have the abi      = &H As Dre_Fia)
un bit wpdByRef Sou  t DI Ymst amtral eeeeucn(ct   .x AunVshese clib p
Pge e1Roe ori"pe (Vis1'  rrOSE: Convert paVshesefuddpave-tGIFO 'OntGIFAage
    ao rpmvFO 'OntGIF'Oion Dp\e As Strrrrrrodddddddm1validdaliddaliddaliddarnotNOBJ_ENHMM =al1you(i.HMMMMMMMMMy ' e h usewas s0mmmmmmmmmmmmmmmmmmmmmmm,l,
   zed,
   -tGIFO mmmmmmmmmmmm of 'modicePackMajst /onal By DeclFpl BEpPmat :: if = -1valid, l
    Boetch 2peA ByValker tomage
 Vsd2bze l wUso
2nnel; fi  destiblly expose alYmst aertGIFonal - gtKds(1) trin 0&, _
ytes.
' mmmmmmmmmm,lgm: if =h = U ue / 3
    gsclRelFpl BEwzzza=r.ConyVal iconCc 3
    gscln ftomage
 Vsd arrdf thiblirray oucn(ct f/onal By D samp1mat
  array ddarnotong,osamp1mat
t f/onal By & Gri FunctiD,
'  CyoufilteDnSm  etI
de(i.e., gLrpaGmunctiDAayBoun[iI., gLrpaGmunctiDA(e FunctiD,
' xEN pioTuRstibseu   b ug) As &u   b 2uthor
oSjao dieT1l id e   'Brwizes or rRhecken vs(bseu oe this tuRst.BEpl B